Titre

------------------------------- Chapitre II - Quelques principes -------------------------------

La limitation de temps

 

Nous allons maintenant by-passer la limitation de temps (time limit). Nous savons que la période d'évaluation est de 30 jours, regardons ce qui se passe après ce délai en avançant la date de l'ordinateur (2 mois, soyons large) . Exécutez XTX-RegMe_NoNag.exe et vous avez droit à ce message :

FinEvaluationDlg

Clic sur OK et c'est fini, nous n'avons plus rien qui s'ouvre. Pour contourner cette protection, nous allons voir différentes approches.

 

1 - La boite de message

Chargez XTX-RegMe_NoNag.exe dans Olly. Le fichier ayant été renommé lors de l'enregistrement de nos modifications, Olly considère que c'est un nouveau programme et effectue une nouvelle analyse. Nos commentaires et breakpoints précédents ont donc disparu. Puisque l'on a une fenêtre qui s'affiche à l'écran, on va reposer nos BP sur les référence à l'API ShowWindow (CTRL+N, clic sur ShowWindow , Find references, F2). On lance avec F9 (ou F9) et ... pas de break. C'est normal car ce que nous avons à l'écran, même si cela y ressemble, n'est pas à proprement parler une fenêtre. Il s'agit d'une boite de message (DialogBox). C'est une sorte de fenêtre simplifiée comportant simplement un message, un ou plusieurs boutons et, éventuellement, une icône. Sa création est donc simplifiée et ne se sert pas de l'API ShowWindow mais uniquement de l'API MessageBox.

Redémarrez la session de débugging avec CTRL+F2 (ou CTRL+F2), CTRL+N pour réafficher nos APIs et effectivement on trouve :

ListAPI

Sélectionnez la ligne, CTRL+R (ou clic droit, Find references) pour afficher les références dans le code :

Reference to MessageBoxA

On pose un BP (F2) sur chaque CALL, excepté le 3eme car on voit bien que le texte passé en argument ne correspond pas à notre message. F9 (ou F9) pour lancer le programme, Olly breake ici (1) :

BP MessageBox

Un peu en dessous de notre CALL, on voit un appel à l'API ExitProcess. C'est elle qui termine le programme lorsque l'on clique sur OK. Regardons maintenant au-dessus ce qu'il se passe. Dans la marge, se trouve une petite flèche (2) : elle indique qu'un saut nous amène à cette ligne et donc indirectement à notre MessageBox. Sélectionnez la ligne correspondante (3) afin que s'affiche dans la fenêtre d'information l'adresse du saut d'origine (4). Clic droit, Go to JA from 00401BAA nous donne ceci :

JA message box

Juste au-dessus du JA (Jump if Above : saut si supérieur), nous avons une comparaison entre la valeur du registre eax et 1Eh (1) soit l'équivalent de 30 en hexadécimal. Ne serais-ce pas le nombre de jours d'évaluation ? Il suffirait donc que le saut ne soit pas effectué et nous pourrions peut être continuer d'utiliser le programme après ce délai. On va tester cela. Posez un BP (F2) sur la ligne du JA, redémarrez la cible avec CTRL+F2 (ou CTRL+F2), lancez avec F9 (ou F9), et on breake sur notre saut. Pour inverser un saut, il n'est pas nécessaire de modifier le code, on peut utiliser les flags (indicateurs ou drapeaux) :

Flags

Ces indicateurs ne peuvent avoir que deux valeurs : 0 ou 1. Ils nous indiquent le résultat d'une opération. Par exemple, dans le cas de notre cmp eax, 1Eh si eax est égal à 1Eh, ZF sera mis à 1 (on parle de ZF, pour Z Flag). Ce qui nous intéresse pour le moment c'est le JA. Pour lui, le saut sera effectué si ZF et CF sont égal à zéro. Il suffit donc de modifier l'un des deux. Sélectionnez par exemple la valeur de ZF, faites Entrée et il passe à 1 (inversement, si il avait été à 1, il serait passé à 0). Vous pouvez voir dans la fenêtre d'information sous le code que l'indication Jump is taken est devenue Jump is not taken. F9 (ou F9) deux fois (Olly breake sur notre précédent BP, ShowWindow) et bingo le programme redémarre. Vous pourriez penser qu'il suffit donc de nopper ce saut comme nous l'avons fait précédemment mais nous constatons que cela provoque un bug dans le titre de la fenêtre :

Bug jours restants

Nous verrons dans la prochaine approche comment le modifier.

 

2 - La recherche de constante

Repartons sur une session de débuging propre. Faîtes tout d'abord un restart (CTRL+F2 ou CTRL+F2) puis cliquez sur ALT+B (ou ALT+B) et effacez tous les BP.

Nous savons que nous avons 30 jours d'évaluation et que 30 converti en hexadécimal donne 1Eh. Nous pouvons donc déduire que, quelque part dans le programme, une comparaison va être faîte entre le nombre de jours restants et cette valeur. Si cette valeur a été saisie en dur dans le code, par exemple :

mov ecx, 1Eh

on parle d'une valeur constante (et nous verrons cette ligne telle quelle dans Olly), en opposition à celle mémorisée dans une variable, par exemple :

.data
;initialisation de la variable avec la valeur 1Eh
MaVariable db 1Eh
 
Code :
...
mov ecx, MaVariable
...

et dont la ligne apparaîtra dans Olly sous la forme :

MOV ECX,DWORD PTR DS:[XTX-RegMe_nonag.4046A0]

[XTX-RegMe_nonag.4046A0] étant l'adresse de l'emplacement mémoire où est stockée la valeur de MaVariable.

Regardons si nous pouvons retrouver des constantes égales à 1Eh. Placez-vous sur la première ligne de code dans Olly, faites un clic droit puis Search for, Constant ...

Search constant

Dans la zone de saisie, tapez 1E (les valeurs de constantes sont toujours en hexadécimal), sélectionnez le type de recherche (Entire block = tout le code, Forward = vers le bas, Backward=vers le haut) puis OK et nous nous retrouvons sur la première occurrence :

cmp E

Ça ne vous rappelle rien ? Nous nous retrouvons juste au-dessus du JA de tout à l'heure. Ici, nous savons que c'est le bon endroit car nous l'avons étudié précédemment. Faisons comme si nous ne l'avions pas fait. Posez un BP sur la ligne, puis faites CTRL+ L (ou clic droit, Search for, Search again). Un deuxième résultat est trouvé. On pose un BP sur la nouvelle ligne, et ainsi de suite tant que l'on trouve la valeur 1Eh (ici nous n'avons que ces deux résultats). On redémarre ( CTRL+F2 ou CTRL+F2), on lance avec F9 ( ou F9) et on breake sur notre CMP. Il ne vous resterait plus qu'à tester l'inversion du saut, mais nous l'avons déjà fait. Comme promis, voyons comment modifier notre code pour avoir un résultat un peu plus élégant.

Pour que le saut ne soit pas pris, il suffit qu'eax soit inférieur à 1Eh. Regardez la ligne au-dessus du CMP. Une valeur est soustraite à eax pour obtenir le résultat qui va être comparé. Cette opération n'a pour nous aucune importance puisque nous voulons donner à eax une valeur fixe inférieure à 1Eh. Autant la remplacer par une instruction fixant cette valeur. D'autre part, cette ligne de code est suffisamment longue pour nous laisser de la marge dans la modification envisagée. Effectivement, lorsque l'on modifie une ligne de code, la nouvelle doit toujours être de longueur inférieure (en complétant avec des NOP) ou égale à l'ancienne (dans sa représentation hexadécimale) mais jamais plus longue sous peine de décaler (ou même fausser) la suite du code. Regardez ce petit exemple :

Nous allons remplacer CMP EAX, 1E (en hexa : 83F81Eh) par MOV DWORD PTR DS:[404880], EAX (en hexa : A380484000h )

Voici le code de départ :

cmp 1E

1er cas : on décoche Keep size puisque l'instruction est plus longue :

Replace cmp

La ligne du CMP a bien été modifiée mais vous pouvez voir que nous avons débordé sur la ligne du JA et que cette ligne a été complétée par des NOP pour arriver à la ligne MOV ECX, 1E. Nous avons donc supprimé une ligne qui pourrait être utile à la bonne continuation du programme.

2eme cas : on décoche aussi Fill rest with NOPs pour supprimer moins de choses :

Replace cmp without NOP

Ici aussi on déborde sur la ligne du JA mais comme nous n'avons pas compléter avec des NOP, le code devient incompréhensible et c'est le crash assuré ...

Voilà pourquoi il faut toujours s'assurer que nous avons la place nécessaire lorsque l'on veut modifier des instructions.

Revenons à notre cas. A la place de la soustraction en 401BA1h, nous allons transférer dans eax la valeur 1 (par exemple, ou n'importe quelle autre valeur tant quelle est inférieure à 1Eh) à l'aide d'un simple MOV. Sélectionnez la ligne, appuyez sur Espace (ou clic droit, Assemble ) puis saisissez notre commande :

Assemble dlg

Vérifiez que les cases Keep size et Fill rest with NOPs soient cochées, Assemble et nous obtenons :

mov eax

Nous n'avons pas débordé sur le CMP EAX, 1E qui suit, c'est parfait. Sélectionnez les lignes modifiées (pour sélectionner plusieurs lignes, soit clic sur la première, maintenez la touche MAJ enfoncée et clic sur la dernière, soit clic sur la première, maintenez la touche CTRL enfoncée et clic sur chaque ligne à sélectionnée), clic droit, Copy to executable puis suivez la procédure pour enregistrer votre exe modifié. Renommez-le par exemple en XTX-RegMe_NoEval.exe.

On va tester notre modification. Ouvrez le nouvel exe obtenu dans Olly. Faites un clic droit puis Search for , Constant ..., recherchez la valeur 1Eh ce qui va vous amener directement sur le CMP. Posez un BP (F2) sur la ligne et lancez avec F9 (ou F9). Olly breake comme prévu :

Jump not taken

On note qu'eax est bien à 1 comme nous le voulions (1). F8 (ou F8) pour passer sur la ligne du saut. Celui-ci ne sera pas effectué (2). F9 (ou F9) et nous obtenons :

Eval 29 jours

Nous avons maintenant éternellement 29 jours d'évaluation et la barre de titre est quand même mieux comme ça qu'avec les hiéroglyphes obtenus en noppant simplement le JA.

 

3 - L'API GetSystemTime

Reprenez dans Olly le XTX-RegMe_nonag.exe et supprimez tous les BP ( ALT+B ou ALT+B).

Pour savoir depuis combien de temps il est installé au moment où on l'ouvre, le programme a forcément besoin de connaitre la date du jour. Faites un CTRL+N (ou clic droit, Search for, Names) et regarder la liste des APIs. Nous pouvons voir quelque chose en rapport avec le temps : GetSystemTime. En effet, cette API récupère le temps au format universel UTC (cela aurait pu être GetLocalTime pour date et temps en local). Voyons si cela peut nous servir.

Sélectionnez cette API, faites CTRL+R (ou clic droit, Find references). Dans la fenêtre qui s'ouvre, nous avons un seul CALL. Cette fois-ci, nous n'allons pas poser directement un BP dessus mais plutôt aller voir où il est utilisé. Faites un double-clic sur la ligne et automatiquement vous vous retrouvez au bon endroit dans la fenêtre code ( ALT+C ou ALT+C si elle n'est plus visible) :

GetSystemTime

Vous pouvez voir l'appel à la fonction avec en arguments les infos qui vont être récupérées (1). Le crochet dans la marge (2) et le RETN à la fin nous indique qu'il s'agit d'une procédure appelée par des CALL. En nous positionnant sur la 1ere ligne de cette procédure, nous pouvons voir ceux-ci (3).

Remontons donc ces appels. Clic sur la ligne Local calls from ... (3) pour la sélectionner, clic droit puis Go to call from 401B9C et nous arrivons dans la zone de test que nous commençons à bien connaître. Mais faisons comme si ... On pose un BP (F2) sur la ligne et pour revenir à notre fonction, il suffit d'appuyer sur Entrée (l'appui sur Entrée lorsqu'on est sur un CALL ou un saut permet d'aller à l'adresse visée sans exécuter le code). Re clic droit puis Go to call from 4020F4 et on pose ici aussi un BP. F9 (ou F9) et bien évidemment Olly va breaker sur le premier CALL juste avant le CMP EAX, 1E.

On en a fini avec le time limit, vous pouvez remettre votre pc à la bonne date.

Tout ce que nous venons de faire pour une seule protection vous montre que plusieurs méthodes sont souvent possible pour arriver au même résultat. Certaines marchent sur un programme et pas sur un autre et vice-versa. C'est surtout, en plus d'un peu de technique, l'observation et la réflexion qui vous permettront d'atteindre vos objectifs.

Continuons à nous entrainer sur notre cible ...

 

 

Precedent        Sommaire        Suivant